//
//  RunLoop.cp
//  WiFiMACSim
//
//  Created by Christopher Kemsley on 3/31/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#include "RunLoop.hpp"
#include "Exception.hpp"


//#define		UseGCD


#ifdef UseGCD
#include <dispatch/dispatch.h>
#endif


SimNamespaceBegin




RunLoop&	RunLoop :: currentRunLoop ()
	{
	static RunLoop s ;
	return s ;
	}


/** Adding/Removing Sources **/

void	RunLoop :: addSource		( RunLoopSource * source , Mode mode )
	{
	if ( source == 0 )
		ThrowException ( "RunLoop" , "Attempted to add nil source" , __FILE__,__LINE__ ) ;
	mSources [mode] . insert ( source ) ;
	}
void	RunLoop :: removeSource		( RunLoopSource * source , Mode mode )
	{
	if ( source == 0 )
		ThrowException ( "RunLoop" , "Attempted to remove nil source" , __FILE__,__LINE__ ) ;
	mSources [mode] . erase ( source ) ;
	}


/** Running the loop **/

void	RunLoop :: runAllModesRepeatedly ( UInteger count )
	{
	while ( count-- )
		runAllModes() ;
	}
void	RunLoop :: runAllModes ()
	{
	runMode ( kModeTime ) ;
	runMode ( kModeSystem ) ;
	runMode ( kModeDefault ) ;
	runMode ( kModeCleanup ) ;
	}
void	RunLoop :: runMode ( Mode mode )
	{
#ifdef UseGCD
	
	dispatch_group_t	group	=	dispatch_group_create() ;
	dispatch_queue_t	queue	=	dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0) ;
	
	Sources & sources	=	mSources[mode] ;
	
	Sources::const_iterator	here	=	sources.begin() ;
	Sources::const_iterator	end		=	sources.end() ;
	while ( here != end )
		{
		RunLoopSource * src = *(here++) ;
		dispatch_group_async ( group , queue , ^{
			try
				{
				src -> runFromRunLoop ( *this , mode ) ;
				}
			CatchException ( "RunLoop" , "Exception while calling run loop source" , __FILE__,__LINE__ ) ;
		}) ;
		}
	
	dispatch_group_wait ( group , DISPATCH_TIME_FOREVER ) ;
	dispatch_release(group) ;
	
#else
	
	Sources & sources	=	mSources[mode] ;
	
	Sources::const_iterator	here	=	sources.begin() ;
	Sources::const_iterator	end		=	sources.end() ;
	while ( here != end )
		{
		RunLoopSource * src = *(here++) ;
		try
			{
			src -> runFromRunLoop ( *this , mode ) ;
			}
		CatchException ( "RunLoop" , "Exception while calling run loop source" , __FILE__,__LINE__ ) ;
		}
	
#endif // ifdef UseGCD
	}






RunLoop :: RunLoop ()
:	mSources ()
	{
	
	}
RunLoop :: ~RunLoop ()
	{
	
	}




SimNamespaceEnd
